#include "eth/eth_nx_driver.h"
#include "eth/eth.h"
#include "debug.h"

/*中断延迟处理*/
#define NX_DRIVER_ENABLE_DEFERRED                /* Define this to enable deferred ISR processing.  */

/* Define the routines for processing each driver entry request.  The contents of these routines will change with
   each driver. However, the main driver entry function will not change, except for the entry function name.  */

static VOID         _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr);
#ifdef NX_DRIVER_ENABLE_DEFERRED
static VOID         _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr);
#endif /* NX_DRIVER_ENABLE_DEFERRED */
static VOID         _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr);

/* Define the prototypes for the hardware implementation of this driver. The contents of these routines are
   driver-specific.  */

static UINT         _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr); 
static UINT         _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr); 
static UINT         _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr); 
static UINT         _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr); 
static UINT         _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_hardware_packet_transmitted(VOID);
static VOID         _nx_driver_hardware_packet_received(VOID);

/* Place Ethernet BD at uncacheable memory*/
static volatile NX_DRIVER_INFORMATION   nx_driver_information;
static UCHAR _nx_driver_hardware_address[] = {MAC_ADDR0,MAC_ADDR1,MAC_ADDR2,MAC_ADDR3,MAC_ADDR4,MAC_ADDR5};

VOID nx_driver_entry(NX_IP_DRIVER *driver_req_ptr)
{
	/* Default to successful return.  */
	driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	
	/* Process according to the driver request type in the IP control 
		 block.  */
	switch (driver_req_ptr -> nx_ip_driver_command)
	{
		case NX_LINK_INTERFACE_ATTACH:
			{
				/* Process link interface attach requests.  */
				_nx_driver_interface_attach(driver_req_ptr);
				break;
			}
    case NX_LINK_INITIALIZE:
			{
				/* Process link initialize requests.  */
				_nx_driver_initialize(driver_req_ptr);
				break;
			}
    case NX_LINK_ENABLE:
			{
				/* Process link enable requests.  */
				_nx_driver_enable(driver_req_ptr);
				break;
			}
    case NX_LINK_DISABLE:
			{
				/* Process link disable requests.  */
				_nx_driver_disable(driver_req_ptr);
				break;
			}
    case NX_LINK_ARP_SEND:
    case NX_LINK_ARP_RESPONSE_SEND:
    case NX_LINK_PACKET_BROADCAST:
    case NX_LINK_RARP_SEND:
    case NX_LINK_PACKET_SEND:
			{
				/* Process packet send requests.  */
				_nx_driver_packet_send(driver_req_ptr);
				break;
			}
    case NX_LINK_MULTICAST_JOIN:
			{
				/* Process multicast join requests.  */
				_nx_driver_multicast_join(driver_req_ptr);
				break;
			}
    case NX_LINK_MULTICAST_LEAVE:
			{
				/* Process multicast leave requests.  */
				_nx_driver_multicast_leave(driver_req_ptr);
				break;
			}
    case NX_LINK_GET_STATUS:
			{
				/* Process get status requests.  */
				_nx_driver_get_status(driver_req_ptr);
				break;
			}
#ifdef NX_DRIVER_ENABLE_DEFERRED
    case NX_LINK_DEFERRED_PROCESSING:
			{
				/* Process driver deferred requests.  */

				/* Process a device driver function on behave of the IP thread. */
				_nx_driver_deferred_processing(driver_req_ptr);

				break;
			}
#endif
    case NX_LINK_GET_SPEED:
			{
				break;
			}
    case NX_LINK_GET_DUPLEX_TYPE:
			{
				break;
			}
    case NX_LINK_GET_ERROR_COUNT:
			{
				break;
			}
    case NX_LINK_GET_RX_COUNT:
			{
				break;
			}
    case NX_LINK_GET_TX_COUNT:
			{
				break;
			}
    case NX_LINK_GET_ALLOC_ERRORS:
			{
				break;
			}
    case NX_LINK_UNINITIALIZE:
			{
				break;
			}
    default:
			/* Invalid driver request.  */

			/* Return the unhandled command status.  */
			driver_req_ptr -> nx_ip_driver_status =  NX_UNHANDLED_COMMAND;

			/* Default to successful return.  */
			driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
	}
}

static VOID  _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr)
{
	/*保存ip驱动接口*/
	/* Setup the driver's interface.  This example is for a simple one-interface
		 Ethernet driver. Additional logic is necessary for multiple port devices.  */
	nx_driver_information.nx_driver_information_interface =  driver_req_ptr -> nx_ip_driver_interface;

	/* Return successful status.  */
	driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
}

static VOID  _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr)
{
	NX_IP           *ip_ptr;
	NX_INTERFACE    *interface_ptr;
	UINT            status;
	
	/*获取ip实例，以知道现在用的哪一个ip实例，执行nx_ip_create时传入的参数*/
	/* Setup the IP pointer from the driver request.  */
	ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

	/*获取ip驱动接口指针*/
	/* Setup interface pointer.  */
	interface_ptr = driver_req_ptr -> nx_ip_driver_interface;

	/* Initialize the driver's information structure.  */

	/* Default IP pointer to NULL.  */
	nx_driver_information.nx_driver_information_ip_ptr =	NX_NULL;

	/*标记驱动未初始化*/
	/* Setup the driver state to not initialized.  */
	nx_driver_information.nx_driver_information_state = 	NX_DRIVER_STATE_NOT_INITIALIZED;

	/*获取包池子，由nx_packet_pool_create进行申请并初始化，执行nx_ip_create时传入的参数*/
	/* Setup the default packet pool for the driver's received packets.  */
	nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool;

	/*清除isr延迟处理事件*/
	/* Clear the deferred events for the driver.  */
	nx_driver_information.nx_driver_information_deferred_events =       0;

	/*调用底层硬件初始化*/
	/* Call the hardware-specific ethernet controller initialization.  */
	status =  _nx_driver_hardware_initialize(driver_req_ptr);

	/* Determine if the request was successful.  */
	if (status == NX_SUCCESS)
	{
		/* Successful hardware initialization.  */

		/*初始化成功则保存nx_ip_create创建的ip实例*/
		/* Setup driver information to point to IP pointer.  */
		nx_driver_information.nx_driver_information_ip_ptr = driver_req_ptr -> nx_ip_driver_ptr;

		/*设置最大传输单元，有API*/
		/* Setup the link maximum transfer unit. */
		interface_ptr -> nx_interface_ip_mtu_size =  NX_DRIVER_ETHERNET_MTU - NX_DRIVER_ETHERNET_FRAME_SIZE;

		/*设置mac地址，有API*/
		/* Setup the physical address of this IP instance.  Increment the 
			 physical address lsw to simulate multiple nodes hanging on the
			 ethernet.  */
		interface_ptr -> nx_interface_physical_address_msw =  
						(ULONG)((_nx_driver_hardware_address[0] << 8) | (_nx_driver_hardware_address[1]));
		interface_ptr -> nx_interface_physical_address_lsw =  
						(ULONG)((_nx_driver_hardware_address[2] << 24) | (_nx_driver_hardware_address[3] << 16) | 
										(_nx_driver_hardware_address[4] << 8) | (_nx_driver_hardware_address[5]));

		/*设置需要地址重映射（需要有效的mac地址），有API*/
		/* Indicate to the IP software that IP to physical mapping
			 is required.  */
		interface_ptr -> nx_interface_address_mapping_needed =  NX_TRUE;

		/*标记驱动已经初始化*/
		/* Move the driver's state to initialized.  */
		nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED;

		/*设置返回状态成功*/
		/* Indicate successful initialize.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	}
	else
	{
		/* Initialization failed.  Indicate that the request failed.  */
		driver_req_ptr -> nx_ip_driver_status =   NX_DRIVER_ERROR;
	}
}

static VOID  _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr)
{
	NX_IP           *ip_ptr;
	UINT            status;

	/* Setup the IP pointer from the driver request.  */
	ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

	/* See if we can honor the NX_LINK_ENABLE request.  */
	if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED)
	{
		/*如果驱动未初始化或初始化失败，则这个请求失败*/
		/* Mark the request as not successful.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;                      
		return;
	}                

	/* Check if it is enabled by someone already */
	if (nx_driver_information.nx_driver_information_state >=  NX_DRIVER_STATE_LINK_ENABLED)
	{
		/*如果驱动状态已经为link（不一定网络真正的link up了），则直接返回*/
		/* Yes, the request has already been made.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_ALREADY_ENABLED;
		return;
	}

	/*调用底层硬件使能*/
	/* Call hardware specific enable.  */
	status =  _nx_driver_hardware_enable(driver_req_ptr);

	/* Was the hardware enable successful?  */
	if (status == NX_SUCCESS)
	{
		/*标记驱动状态为link*/
		/* Update the driver state to link enabled.  */
		nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED;

		/*设置返回状态*/
		/* Mark request as successful.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;

		/*标记ip实例为link*/
		/* Mark the IP instance as link up.  */        
		ip_ptr -> nx_ip_driver_link_up =  NX_TRUE;
	}
	else
	{
		/* Enable failed.  Indicate that the request failed.  */
		driver_req_ptr -> nx_ip_driver_status =   NX_DRIVER_ERROR;
	}
}

static VOID  _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr)
{
	NX_IP           *ip_ptr;
	UINT            status;

	/* Setup the IP pointer from the driver request.  */
	ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

	/* Check if the link is enabled.  */
	if (nx_driver_information.nx_driver_information_state !=  NX_DRIVER_STATE_LINK_ENABLED)
	{
		/*如果驱动状态不为link，则这个请求失败*/
		/* The link is not enabled, so just return an error.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
		return;
	}

	/*调用底层硬件失能*/
	/* Call hardware specific disable.  */
	status =  _nx_driver_hardware_disable(driver_req_ptr);

	/* Was the hardware disable successful?  */
	if (status == NX_SUCCESS)
	{
		/*标记ip实例未link*/
		/* Mark the IP instance as link down.  */        
		ip_ptr -> nx_ip_driver_link_up =  NX_FALSE;

		/*标记驱动状态为已初始化*/
		/* Update the driver state back to initialized.  */
		nx_driver_information.nx_driver_information_state =  NX_DRIVER_STATE_INITIALIZED;

		/*设置返回状态*/
		/* Mark request as successful.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	}
	else
	{
		/* Disable failed, return an error.  */    
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
	}
}

static VOID  _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr)
{
	NX_IP           *ip_ptr;
	NX_PACKET       *packet_ptr;
	ULONG           *ethernet_frame_ptr;
	UINT            status;

	/* Setup the IP pointer from the driver request.  */
	ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

	/* Check to make sure the link is up.  */
	if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED)
	{
		/*如果驱动未link，则这个请求失败*/
		/* Inidate an unsuccessful packet send.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;

		/*释放此包数据*/
		/* Link is not up, simply free the packet.  */
		nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet);
		return;
	}

	/* Process driver send packet.  */

	/*获取要发送的报文包指针*/
	/* Place the ethernet frame at the front of the packet.  */
	packet_ptr =  driver_req_ptr -> nx_ip_driver_packet;

	/*调整指针到包头的位置*/
	/* Adjust the prepend pointer.  */
	packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_DRIVER_ETHERNET_FRAME_SIZE;

	/*增加包头的长度*/
	/* Adjust the packet length.  */
	packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_DRIVER_ETHERNET_FRAME_SIZE;

	/*因为有两个对齐字节，所以要减去对齐字节数*/
	/* Setup the ethernet frame pointer to build the ethernet frame.  Backup another 2
		* bytes to get 32-bit word alignment.  */
	ethernet_frame_ptr =  (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 2);

	/*构建以太帧*/
	/* Set up the hardware addresses in the Ethernet header. */
	/*填充目的mac地址*/
	*ethernet_frame_ptr       =  driver_req_ptr -> nx_ip_driver_physical_address_msw;
	*(ethernet_frame_ptr + 1) =  driver_req_ptr -> nx_ip_driver_physical_address_lsw;
	/*填充源mac地址*/
	*(ethernet_frame_ptr + 2) =  (ip_ptr -> nx_ip_arp_physical_address_msw << 16) |
															 (ip_ptr -> nx_ip_arp_physical_address_lsw >> 16);
	*(ethernet_frame_ptr + 3) =  (ip_ptr -> nx_ip_arp_physical_address_lsw << 16);

	/*填充帧类型字段*/
	/* Set up the frame type field in the Ethernet harder. */
	if ((driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_SEND)||
			(driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND))
	{
		/*ARP包*/
		*(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_ARP;
	}
	else if(driver_req_ptr -> nx_ip_driver_command == NX_LINK_RARP_SEND)
	{
		/*RARP包*/
		*(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_RARP;        
	}
	else
	{
		/*IP包*/
		*(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IP;
	}

	/*大小端交换*/
	/* Endian swapping if NX_LITTLE_ENDIAN is defined.  */
	NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr));
	NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1));
	NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2));
	NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3));

	/* Determine if the packet exceeds the driver's MTU.  */
	if (packet_ptr -> nx_packet_length > NX_DRIVER_ETHERNET_MTU)
	{
		/*如果包长度超出了最大传输单元，则释放丢掉此包（感觉这里应该特殊处理，而不是直接丢掉）*/
		/* This packet exceeds the size of the driver's MTU. Simply throw it away! */

		/*移除包头*/
		/* Remove the Ethernet header.  */
		NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr);

		/*标记此包未成功发送*/
		/* Indicate an unsuccessful packet send.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;

		/*释放掉此包*/
		/* Link is not up, simply free the packet.  */
		nx_packet_transmit_release(packet_ptr);
		return;
	}

	/*调用底层硬件发送数据包*/
	/* Transmit the packet through the Ethernet controller low level access routine. */
	status = _nx_driver_hardware_packet_send(packet_ptr);

	/* Determine if there was an error.  */
	if (status != NX_SUCCESS)
	{
		/*发送失败*/
		/* Driver's hardware send packet routine failed to send the packet.  */

		/*移除包头*/
		/* Remove the Ethernet header.  */
		NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr);

		/*标记包发送失败*/
		/* Indicate an unsuccessful packet send.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;

		/*释放掉包资源*/
		/* Link is not up, simply free the packet.  */
		nx_packet_transmit_release(packet_ptr);
	}
	else
	{
		/* Set the status of the request.  */    
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	}
}

static VOID  _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr)
{
	UINT        status;

	/* Call hardware specific multicast join function. */
	status =  _nx_driver_hardware_multicast_join(driver_req_ptr);

	/* Determine if there was an error.  */
	if (status != NX_SUCCESS)
	{
		/* Indicate an unsuccessful request.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
	}
	else
	{
		/* Indicate the request was successful.   */    
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	}
}

static VOID  _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr)
{
	UINT        status;

	/* Call hardware specific multicast leave function. */
	status =  _nx_driver_hardware_multicast_leave(driver_req_ptr);

	/* Determine if there was an error.  */
	if (status != NX_SUCCESS)
	{
		/* Indicate an unsuccessful request.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
	}
	else
	{
		/* Indicate the request was successful.   */    
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	}
}

static VOID  _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr)
{
	UINT        status;

	/* Call hardware specific get status function. */
	status =  _nx_driver_hardware_get_status(driver_req_ptr);

	/* Determine if there was an error.  */
	if (status != NX_SUCCESS)
	{
		/* Indicate an unsuccessful request.  */
		driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
	}
	else
	{
		/* Indicate the request was successful.   */    
		driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
	}
}

#ifdef NX_DRIVER_ENABLE_DEFERRED
static VOID  _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr)
{
	TX_INTERRUPT_SAVE_AREA

	ULONG       deferred_events;

	/* Disable interrupts.  */
	TX_DISABLE

	/*获取延迟处理事件，在中断中被设置*/
	/* Pickup deferred events.  */
	deferred_events =  nx_driver_information.nx_driver_information_deferred_events;
	nx_driver_information.nx_driver_information_deferred_events =  0;

	/* Restore interrupts.  */
	TX_RESTORE

	/* Check for a transmit complete event.  */
	if(deferred_events & NX_DRIVER_DEFERRED_PACKET_TRANSMITTED)
	{
		/*如果得到了一个发送完成事件*/
		/* Process transmitted packet(s).  */
		_nx_driver_hardware_packet_transmitted();
	}    

	/* Check for recevied packet.  */
	if(deferred_events & NX_DRIVER_DEFERRED_PACKET_RECEIVED)
	{
		/*如果得到了一个接收接收事件*/
		/* Process received packet(s).  */
		_nx_driver_hardware_packet_received();
	}

	/*标记返回状态*/
	/* Mark request as successful.  */    
	driver_req_ptr->nx_ip_driver_status =  NX_SUCCESS;
}
#endif /* NX_DRIVER_ENABLE_DEFERRED */

static VOID _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
{
	USHORT    packet_type;

	/* Set the interface for the incoming packet.  */
	packet_ptr -> nx_packet_ip_interface = nx_driver_information.nx_driver_information_interface;

	/*获取包类型*/
	/* Pickup the packet header to determine where the packet needs to be
		 sent.  */
	packet_type =  (USHORT)(((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+12))) << 8) |
													((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+13)));

	/* Route the incoming packet according to its ethernet type.  */
	if (packet_type == NX_DRIVER_ETHERNET_IP || packet_type == NX_DRIVER_ETHERNET_IPV6)
	{
		/* Note:  The length reported by some Ethernet hardware includes 
			 bytes after the packet as well as the Ethernet header.  In some 
			 cases, the actual packet length after the Ethernet header should 
			 be derived from the length in the IP header (lower 16 bits of
			 the first 32-bit word).  */

		/* Clean off the Ethernet header.  */
		packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE;

		/* Adjust the packet length.  */
		packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE;

		/* Route to the ip receive function.  */
#ifdef NX_DRIVER_ENABLE_DEFERRED
		/*得到一个IP包*/
		_nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
#else
		_nx_ip_packet_receive(ip_ptr, packet_ptr);
#endif /* NX_DRIVER_ENABLE_DEFERRED */
	}
	else if (packet_type == NX_DRIVER_ETHERNET_ARP)
	{
			/* Clean off the Ethernet header.  */
			packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE;

			/* Adjust the packet length.  */
			packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE;

			/*得到一个ARP包*/
			/* Route to the ARP receive function.  */
			_nx_arp_packet_deferred_receive(ip_ptr, packet_ptr);
	}
	else if (packet_type == NX_DRIVER_ETHERNET_RARP)
	{
		/* Clean off the Ethernet header.  */
		packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE;

		/* Adjust the packet length.  */
		packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE;

		/*得到一个RARP包*/
		/* Route to the RARP receive function.  */
		_nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr);
	}
	else
	{
		/* Invalid ethernet header... release the packet.  */
		nx_packet_release(packet_ptr);
	}
}

static UINT  _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr)
{
	NX_PACKET           *packet_ptr;
	UINT                i;
	ETH_DMADescTypeDef  *DMATxDesc;
	ETH_DMADescTypeDef  *DMARxDesc;

	/* Default to successful return.  */
	driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;

	/* Setup indices.  */
	nx_driver_information.nx_driver_information_receive_current_index = 0; 
	nx_driver_information.nx_driver_information_transmit_current_index = 0; 
	nx_driver_information.nx_driver_information_transmit_release_index = 0;

	/* Clear the number of buffers in use counter.  */
	nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = 0;

	/* Make sure there are receive packets... otherwise, return an error.  */
	if (nx_driver_information.nx_driver_information_packet_pool_ptr == NULL)
	{
		/*确保包池子已准备好，否则返回错误*/
		/* There must be receive packets. If not, return an error!  */
		return(NX_DRIVER_ERROR);
	}

	/*初始化mac控制器和dma*/
	eth_init();

	/* Initialize TX Descriptors list: Ring Mode.  */

	/*下面两部分在HAL库中有对应的API也就是HAL_ETH_DMATxDescListInit和HAL_ETH_DMARxDescListInit，但是有点区别*/
	/* Fill each DMATxDesc descriptor with the right values.  */   
	for(i = 0; i < NX_DRIVER_TX_DESCRIPTORS; i++)
	{
		/* Get the pointer on the ith member of the Tx Desc list.  */
		DMATxDesc = (ETH_DMADescTypeDef  *)&nx_driver_information.nx_driver_information_dma_tx_descriptors[i];

#ifdef HARDWARE_CHECKSUM_ENABLE
		/* Set Second Address Chained bit and checksum offload options.  */
		DMATxDesc -> Status = ETH_DMATXDESC_TCH | ETH_DMATXDESC_IC | ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_CIC_IPV4HEADER;        
#else
		/* Set Second Address Chained bit.  */
		DMATxDesc -> Status = ETH_DMATXDESC_TCH | ETH_DMATXDESC_IC;        
#endif

		/* Initialize the next descriptor with the Next Descriptor Polling Enable */
		if(i < (NX_DRIVER_TX_DESCRIPTORS - 1))
		{
			/* Set next descriptor address register with next descriptor base address */
			DMATxDesc -> Buffer2NextDescAddr = (ULONG)(nx_driver_information.nx_driver_information_dma_tx_descriptors + i + 1);
		}
		else
		{
			/* For last descriptor, set next descriptor address register equal to the first descriptor base address */ 
			DMATxDesc -> Buffer2NextDescAddr = (ULONG) nx_driver_information.nx_driver_information_dma_tx_descriptors;  
		}
		nx_driver_information.nx_driver_information_transmit_packets[i] = NX_NULL;
	}

	/* Set Transmit Descriptor List Address Register */
	ETH -> DMATDLAR = (ULONG) nx_driver_information.nx_driver_information_dma_tx_descriptors;

	/* Initialize RX Descriptors list: Ring Mode  */

	DMARxDesc = (ETH_DMADescTypeDef  *)nx_driver_information.nx_driver_information_dma_rx_descriptors;

	/* Fill each DMARxDesc descriptor with the right values */  
	for(i = 0; i < NX_DRIVER_RX_DESCRIPTORS; i++)
	{
		/*从包池子中申请一个packet*/
		/* Allocate a packet for the receive buffers.  */
		if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS)
		{
			/*这里感觉是因为4字节对齐的原因，因为帧格式(Ethernet II)为6+6+2+(46~1500)+4，
			创建包时因为对齐所以在最前面填充了两个字节用于对齐，即2+6+6+2+(46~1500)+4，所以
			实际上要将nx_packet_prepend_ptr+2才是真正的数据存放地址*/
			/* Adjust the packet.  */
			packet_ptr -> nx_packet_prepend_ptr += 2;
			DMARxDesc[i].Buffer1Addr =          (uint32_t) packet_ptr -> nx_packet_prepend_ptr;
			DMARxDesc[i].ControlBufferSize =    ETH_DMARXDESC_RCH | (packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start);

			/*保存这个packet的地址*/
			/* Remember the receive packet poitner.  */
			nx_driver_information.nx_driver_information_receive_packets[i] = packet_ptr;

			/* Set Own bit of the RX descriptor Status.  */
			DMARxDesc[i].Status =  ETH_DMARXDESC_OWN;      
		}
		else
		{
			/* Cannot allocate packets from the packet pool. */
			return(NX_DRIVER_ERROR);
		}

		/* Initialize the next descriptor with the Next Descriptor Polling Enable.  */
		if(i < (NX_DRIVER_RX_DESCRIPTORS - 1))
		{
			/* Set next descriptor address register with next descriptor base address.  */
			DMARxDesc[i].Buffer2NextDescAddr = (ULONG)(nx_driver_information.nx_driver_information_dma_rx_descriptors + i + 1); 
		}
		else
		{
			/* For last descriptor, set next descriptor address register equal to the first descriptor base address.  */ 
			DMARxDesc[i].Buffer2NextDescAddr = (uint32_t)(nx_driver_information.nx_driver_information_dma_rx_descriptors); 
		}
	}

	/* Save the size of one rx buffer.  */
	nx_driver_information.nx_driver_information_rx_buffer_size = packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start;

	/* Clear the number of buffers in use counter.  */
	nx_driver_information.nx_driver_information_multicast_count = 0;

	/* Set Receive Descriptor List Address Register */
	ETH -> DMARDLAR = (ULONG) nx_driver_information.nx_driver_information_dma_rx_descriptors;  

	/* Return success!  */
	return(NX_SUCCESS);
}

static UINT  _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr)
{
	eth_start();

	/* Return success!  */
	return(NX_SUCCESS);
}

static UINT  _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr)
{
	eth_stop();

	/* Return success!  */
	return(NX_SUCCESS);
}

static UINT  _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr)
{
	ULONG           curIdx;
	NX_PACKET       *pktIdx;
	ULONG            bd_count = 0;
	TX_INTERRUPT_SAVE_AREA

	/*获取要发送的包的当前描述符索引*/
	/* Pick up the first BD. */
	curIdx = nx_driver_information.nx_driver_information_transmit_current_index;

	/* Check if it is a free descriptor.  */
	if ((nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status & ETH_DMATXDESC_OWN) || nx_driver_information.nx_driver_information_transmit_packets[curIdx])
	{
		/*如果这个描述符已释放或未初始化，则标记失败*/
		/* Buffer is still owned by device.  */
		return(NX_DRIVER_ERROR);
	}

	/*将数据包指针放到描述符的buffer1地址指针*/
	/* Find the Buffer, set the Buffer pointer.  */
	nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Buffer1Addr = (ULONG)packet_ptr->nx_packet_prepend_ptr;

	/*设置buffer的大小*/
	/* Set the buffer size.  */
	nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].ControlBufferSize = ((packet_ptr -> nx_packet_append_ptr - packet_ptr->nx_packet_prepend_ptr) & ETH_DMATXDESC_TBS1);

	/* Set the first Descriptor's FS bit.  */
	nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status |= ETH_DMATXDESC_FS;

	/* Clear the first Descriptor's LS bit.  */
	nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status &= ~ETH_DMATXDESC_LS;

	/* Find next packet.  */
	for (pktIdx = packet_ptr -> nx_packet_next;
			 pktIdx != NX_NULL;
			 pktIdx = pktIdx -> nx_packet_next)
	{
		/* Move to next descriptor.  */
		curIdx = (curIdx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1);
				
		/* Check if it is a free descriptor.  */
		if ((nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status & ETH_DMATXDESC_OWN) || nx_driver_information.nx_driver_information_transmit_packets[curIdx])
		{
			/* No more descriptor available, return driver error status.  */
			return(NX_DRIVER_ERROR);
		}

		/* Set the buffer pointer.  */
		nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Buffer1Addr = (ULONG)pktIdx -> nx_packet_prepend_ptr;

		/* Set the buffer size.  */
		nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].ControlBufferSize = ((pktIdx -> nx_packet_append_ptr - pktIdx -> nx_packet_prepend_ptr) & ETH_DMATXDESC_TBS1); 

		/* Clear the descriptor's FS & LS bit.  */
		nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status &= ~(ETH_DMATXDESC_FS | ETH_DMATXDESC_LS);

		/* Increment the BD count.  */
		bd_count++;
	}

	/* Set the last Descriptor's LS & IC & OWN bit.  */
	nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status |= (ETH_DMATXDESC_LS | ETH_DMATXDESC_IC | ETH_DMATXDESC_OWN);

	/* Save the pkt pointer to release.  */
	nx_driver_information.nx_driver_information_transmit_packets[curIdx] = packet_ptr;

	/* Set the current index to the next descriptor.  */
	nx_driver_information.nx_driver_information_transmit_current_index = (curIdx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1);

	TX_DISABLE
	/* Increment the transmit buffers in use count.  */
	nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use += bd_count + 1;
	TX_RESTORE

	/* Set OWN bit to indicate BDs are ready.  */
	for (; bd_count > 0; bd_count--)
	{
		/* Set OWN bit in reverse order, move to prevous BD.  */
		curIdx = (curIdx - 1) & (NX_DRIVER_TX_DESCRIPTORS - 1);

		/* Set this BD's OWN bit.  */
		nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].Status |= ETH_DMATXDESC_OWN;
	}

	/* If the DMA transmission is suspended, resume transmission.  */
	if ((ETH -> DMASR & ETH_DMASR_TBUS) != (ULONG)RESET)
	{
		/* Clear TBUS ETHERNET DMA flag.  */
		ETH -> DMASR = ETH_DMASR_TBUS;

		/* Resume DMA transmission. */
		ETH -> DMATPDR = 0;
	}

	return(NX_SUCCESS);
}

static UINT  _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr)
{
	/* Increase the multicast count.  */
	nx_driver_information.nx_driver_information_multicast_count++;

	/* Enable multicast frame reception.  */
	ETH->MACFFR |= ETH_MACFFR_PAM;

	/* Return success.  */
	return(NX_SUCCESS);
}

static UINT  _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr)
{
	/* Decrease the multicast count.  */
	nx_driver_information.nx_driver_information_multicast_count--;

	/* If multicast count reachs zero, disable multicast frame reception.  */
	if (nx_driver_information.nx_driver_information_multicast_count == 0)
	{
		/* Disable multicast frame reception.  */
		ETH->MACFFR &= ~ETH_MACFFR_PAM;
	}

	/* Return success.  */
	return(NX_SUCCESS);
}

static UINT  _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr)
{
	/* Return success.  */
	return(NX_SUCCESS);
}

static VOID  _nx_driver_hardware_packet_transmitted(VOID)
{
	/*获取正在使用的发送buf的数量*/
	ULONG numOfBuf =  nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use;
	ULONG idx =       nx_driver_information.nx_driver_information_transmit_release_index;

	/*遍历所有正在使用的包*/
	/* Loop through buffers in use.  */
	while (numOfBuf--)
	{
		/* If no packet, just examine the next packet.  */
		if (nx_driver_information.nx_driver_information_transmit_packets[idx] == NX_NULL) 
		{
			/* No packet in use, skip to next.  */
			idx = (idx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1);
			continue;
		}

		/* Determine if the packet has been transmitted.  */
		if ((nx_driver_information.nx_driver_information_dma_tx_descriptors[idx].Status & ETH_DMATXDESC_OWN) == 0)
		{
			/*如果包已经被发送*/
			/* Yes, packet has been transmitted.  */

			/*移除包头*/
			/* Remove the Ethernet header and release the packet.  */
			NX_DRIVER_ETHERNET_HEADER_REMOVE(nx_driver_information.nx_driver_information_transmit_packets[idx]);

			/*释放包资源*/
			/* Release the packet.  */
			nx_packet_transmit_release(nx_driver_information.nx_driver_information_transmit_packets[idx]);

			/* Clear the entry in the in-use array.  */
			nx_driver_information.nx_driver_information_transmit_packets[idx] = NX_NULL;

			/* Update the transmit relesae index and number of buffers in use.  */
			idx = (idx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1);
			nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = numOfBuf;
			nx_driver_information.nx_driver_information_transmit_release_index = idx;
		}
		else
		{
			/* Get out of the loop!  */
			break;
		}
	}
}

static VOID  _nx_driver_hardware_packet_received(VOID)
{
	NX_PACKET     *packet_ptr;
	ULONG          bd_count = 0;
	INT            i;
	ULONG          idx;
	ULONG          temp_idx;
	ULONG          first_idx = nx_driver_information.nx_driver_information_receive_current_index;
	NX_PACKET     *received_packet_ptr = nx_driver_information.nx_driver_information_receive_packets[first_idx];
 
	/* Find out the BDs that owned by CPU.  */
	for (first_idx = idx = nx_driver_information.nx_driver_information_receive_current_index;
			(nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].Status & ETH_DMARXDESC_OWN) == 0;
			 idx = (idx + 1) & (NX_DRIVER_RX_DESCRIPTORS - 1))
	{
		/* Is the BD marked as the end of a frame?  */
		if (nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].Status & ETH_DMARXDESC_LS)
		{
			/* Yes, this BD is the last BD in the frame, set the last NX_PACKET's nx_packet_next to NULL.  */
			nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_next = NX_NULL;

			/* Store the length of the packet in the first NX_PACKET.  */
			nx_driver_information.nx_driver_information_receive_packets[first_idx] -> nx_packet_length = ((nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4;

			/* Adjust nx_packet_append_ptr with the size of the data in this buffer.  */
			nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_append_ptr = nx_driver_information.nx_driver_information_receive_packets[idx]->nx_packet_prepend_ptr
																																															 + nx_driver_information.nx_driver_information_receive_packets[first_idx]->nx_packet_length
																																															 - bd_count * nx_driver_information.nx_driver_information_rx_buffer_size;
			/* Is there only one BD for the current frame?  */
			if (idx != first_idx)
			{
				/* No, this BD is not the first BD of the frame, frame data starts at the aligned address.  */
				nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_prepend_ptr -= 2;

				if (nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_prepend_ptr >= nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_append_ptr)
				{
					temp_idx = (idx - 1) & (NX_DRIVER_RX_DESCRIPTORS - 1);
					nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_next = NX_NULL;
					nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_append_ptr -= nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_prepend_ptr >= nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_append_ptr;
					nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].Status = ETH_DMARXDESC_OWN;
					nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_prepend_ptr = nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_data_start + 2;
					bd_count--;
				}
			}

			/* Allocate new NX_PACKETs for BDs.  */
			for (i = bd_count; i >= 0; i--)
			{
				temp_idx = (first_idx + i) & (NX_DRIVER_RX_DESCRIPTORS - 1);

				/* Allocate a new packet from the packet pool.  */
				if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS)
				{
					/* Adjust the new packet and assign it to the BD.  */
					packet_ptr -> nx_packet_prepend_ptr += 2;
					nx_driver_information.nx_driver_information_dma_rx_descriptors[temp_idx].Buffer1Addr = (ULONG)packet_ptr->nx_packet_prepend_ptr;
					nx_driver_information.nx_driver_information_dma_rx_descriptors[temp_idx].Status = ETH_DMARXDESC_OWN;
					nx_driver_information.nx_driver_information_receive_packets[temp_idx] = packet_ptr;
				}
				else
				{
					/* Allocation failed, get out of the loop.  */
					break;
				}
			}

			if (i >= 0)
			{
				/* At least one packet allocation was failed, release the received packet.  */
				nx_packet_release(nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_next);

				for (; i >= 0; i--)
				{
					/* Free up the BD to ready state. */
					temp_idx = (first_idx + i) & (NX_DRIVER_RX_DESCRIPTORS - 1);
					nx_driver_information.nx_driver_information_dma_rx_descriptors[temp_idx].Status = ETH_DMARXDESC_OWN;
					nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_prepend_ptr = nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_data_start + 2;
				}
			}
			else
			{
				/* Everything is OK, transfer the packet to NetX.  */
				_nx_driver_transfer_to_netx(nx_driver_information.nx_driver_information_ip_ptr, received_packet_ptr);
			}

			/* Set the first BD index for the next packet.  */
			first_idx = (idx + 1) & (NX_DRIVER_RX_DESCRIPTORS - 1);

			/* Update the current receive index.  */
			nx_driver_information.nx_driver_information_receive_current_index = first_idx;

			received_packet_ptr = nx_driver_information.nx_driver_information_receive_packets[first_idx];

			bd_count = 0;
		}
		else
		{
			/* This BD is not the last BD of a frame. It is a intermediate descriptor.  */

			nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_next = nx_driver_information.nx_driver_information_receive_packets[(idx + 1) & (NX_DRIVER_RX_DESCRIPTORS - 1)];

			nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_append_ptr = nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_data_end;

			if (idx != first_idx)
			{
				nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_prepend_ptr = nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_data_start;
			}

			bd_count++;
		}
	}

	/* If Rx DMA is in suspended state, resume it.  */
	if ((ETH->DMASR & ETH_DMASR_RBUS) != (ULONG)RESET)  
	{
		/* Clear RBUS ETHERNET DMA flag */
		ETH->DMASR = ETH_DMASR_RBUS;
		/* Resume DMA reception */
		ETH->DMARPDR = 0;
	}
}

VOID  ETH_IRQHandler(VOID)
{
	ULONG status;
#ifdef NX_DRIVER_ENABLE_DEFERRED
	ULONG deffered_events;
#endif /* NX_DRIVER_ENABLE_DEFERRED */

	/*获取中断状态寄存器得值*/
	status = ETH->DMASR;

	/*清除中断挂起位*/
	/* Clear the Ethernet DMA Rx IT pending bits */
	ETH->DMASR = ETH_DMA_IT_R | ETH_DMA_IT_T | ETH_DMA_IT_NIS;

#ifdef NX_DRIVER_ENABLE_DEFERRED
	/*读取延迟处理事件*/
	deffered_events = nx_driver_information.nx_driver_information_deferred_events;
#endif /* NX_DRIVER_ENABLE_DEFERRED */

	/* Interrupt on transmit completion.  */
	if(status & ETH_DMA_IT_T)
	{
#ifdef NX_DRIVER_ENABLE_DEFERRED
		/*标记一个发送完成事件*/
		/* Set the transmit complete bit.  */
		nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_TRANSMITTED;
#else
		/* Process transmitted packet(s).  */
		_nx_driver_hardware_packet_transmitted();
#endif /* NX_DRIVER_ENABLE_DEFERRED */
	}
	
	/* Receive packet interrupt.  */
	if(status & ETH_DMA_IT_R)
	{
#ifdef NX_DRIVER_ENABLE_DEFERRED
		/*标记一个接收完成事件*/
		/* Set the receive packet interrupt.  */
		nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_RECEIVED;
#else
		/* Process received packet(s).  */
		_nx_driver_hardware_packet_received();
#endif /* NX_DRIVER_ENABLE_DEFERRED */
	}

#ifdef NX_DRIVER_ENABLE_DEFERRED
	if (!deffered_events)
	{
		/*如果没有正在处理的事件，则发出一个通知唤醒内部线程并产生NX_LINK_DEFERRED_PROCESSING命令*/
		/* Call NetX deferred driver processing.  */        
		_nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr);
	}
#endif /* NX_DRIVER_ENABLE_DEFERRED */
}
